namespace ScrumSprintMonitor.Modules.WorkItemMonitor.ViewModels
{
	#region #using Directives

	using System;
	using System.Collections.Generic;
	using System.Linq;

	using Infrastructure;

	using UI.Wpf;

	#endregion

	internal static class BurndownChartHelper
	{
		internal static void CalculateBurndownTrendLineDataPointList(ICollection<BurndownDataPoint> burndownTrendLineDataPointList,
		                                                             IEnumerable<BurndownDataPoint> burndownDataPoints, DateTime minimumDate,
		                                                             DateTime burndownChartEndDate)
		{
			burndownTrendLineDataPointList.Clear();

			if (burndownDataPoints != null && burndownDataPoints.Count() >= 2)
			{
				var dataPointsByDate = burndownDataPoints.GroupBy(x => x.Time);
				var xValues = new List<double>(32);
				var yValues = new List<double>(32);
				var validDays = dataPointsByDate.Select(x => x.Key).ToList();
				validDays.Sort();
				foreach (var dataPointsInTimeStamp in dataPointsByDate)
				{
					double workRemaining = dataPointsInTimeStamp.Sum(x => x.WorkRemaining);

					xValues.Add(GetXAxisOffset(dataPointsInTimeStamp.Key, minimumDate, validDays));
					yValues.Add(workRemaining);
				}

				if (xValues.Count >= 2 && xValues.Any(x => x >= 1.0))
				{
					var trendLine = new Trendline(yValues, xValues);
					var trendLineEnd = burndownChartEndDate;
					double projectedWorkRemainingAtEndDate = trendLine.CalculateEnd(GetXAxisOffset(trendLineEnd, minimumDate, validDays));
					burndownTrendLineDataPointList.Add(new BurndownDataPoint
					                                   	{
					                                   		Time = minimumDate,
					                                   		WorkRemaining = trendLine.Start
					                                   	});
					burndownTrendLineDataPointList.Add(new BurndownDataPoint
					                                   	{
					                                   		Time = trendLineEnd,
					                                   		WorkRemaining = projectedWorkRemainingAtEndDate
					                                   	});
				}
			}
		}

		private static double GetXAxisOffset(DateTime dateTime, DateTime minimumDate, ICollection<DateTime> validDays)
		{
			double offset = 0.0;
			var lastValidDate = minimumDate;

			for (var d = minimumDate.AddDays(1.0); d <= dateTime; d = d.AddDays(1.0))
			{
				if (validDays.Contains(d))
				{
					lastValidDate = d;
					offset += 1.0;
				}
			}

			offset += (dateTime - lastValidDate).TotalDays;

			return offset;
		}
	}
}